package tx.service;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Random;

/**
 * @author jackcfan
 * @date 22/10/1
 */
@Service
public class UserService {
  @Resource
  JdbcTemplate jdbcTemplate;
  @Resource
  PlatformTransactionManager transactionManager;
  @Resource
  TransactionTemplate transactionTemplate;
  @Resource
  UserService userService;

  /**
   * 编程式事务
   * */
  public void programedTransaction(){
    TransactionStatus transactionStatus = transactionManager.getTransaction(new DefaultTransactionDefinition());
    try {
      jdbcTemplate.update("update user set age = ?,update_time = ? where id = ?", new Random().nextInt(60),new Date(), 1);
      transactionManager.commit(transactionStatus);
    }catch (Exception e){
      e.printStackTrace();
      transactionManager.rollback(transactionStatus);
    }
  }

  public void transactionTemplateTransaction(){
    transactionTemplate.execute(new TransactionCallbackWithoutResult() {
      @Override
      protected void doInTransactionWithoutResult(TransactionStatus status) {
        try {
          jdbcTemplate.update("update user set age = ?,update_time = ? where id = ?", new Random().nextInt(60),new Date(), 1);
          int i = 1/0;
        }catch (Exception e){
          // 设置回滚
          status.setRollbackOnly();
          e.printStackTrace();
        }
      }
    });
  }

  /**
   * 调用代理对象的 updateNoTransaction 方法，由于当前已经开启了事务，所以 updateNoTransaction 会报错
   * */
  @Transactional
  public void proxyUpdate(){
    jdbcTemplate.update("update user set email = ?,update_time = ? where id = ?",
            "proxyUpdate@one.com",new Date(), 1);
    userService.updateNoTransaction();
  }

  /**
   * 调用 updateNoTransaction，只是作为普通方法，并不会触发传播机制，也就不会报错
   * */
  @Transactional
  public void normalTargetUpdate(){
    jdbcTemplate.update("update user set email = ?,update_time = ? where id = ?",
            "normalTargetUpdate@one.com",new Date(), 1);
    /**
     * 进入到方法内部后，方法内的调用是普通对象调用
     * 普通对象的方法调用，非代理对象，无法触发事务传播
     * */
    updateNoTransaction();
  }

  /**
   * 如果有事务就报错
   * */
  @Transactional(propagation = Propagation.NEVER)
  public void updateNoTransaction(){
    jdbcTemplate.update("update user set email = ?,update_time = ? where id = ?",
            "updateNoTransaction@one.com",new Date(), 1);
  }
}
